#include "gwbase/base/test_util.h"
#include "gwbase/encrypt/digest.h"
#include "gwbase/base/logging.h"

namespace dicom {

static const char kAlphabet[] = {
    "1234567890abcdefghijklmnopqrstyvwxyzABCDEFGHIJKLMNOPQRSTYVWXYZ=_."};

std::string RandomString(Random* rand, size_t len) {
  std::string result;
  for (size_t i = 0; i < len; ++i) {
    result.push_back(kAlphabet[rand->Next() % sizeof(kAlphabet)]);
  }
  return result;
}

bool CreateRandomFile(const std::string& path, Random* rand, size_t len) {
  WritableFilePtr f;
  Status s = WritableFile::Open(path, true, &f);
  if (!s.ok()) {
    LOG_ERROR << "failed to create file: " << path;
    return false;
  }

  const size_t kBlockSize = 1024;
  char buf[kBlockSize];
  size_t blocks = len / kBlockSize;
  size_t remain = len % kBlockSize;

  for (size_t i = 0; i < kBlockSize; ++i) {
    buf[i] = static_cast<char>(rand->Next() % 128);
  }

  for (size_t i = 0; i < blocks; ++i) f->Append(Slice(buf, kBlockSize));
  if (remain > 0) f->Append(Slice(buf, remain));
  f->Sync();
  return true;
}

void CreateTestFile(const std::string& name, size_t size, bool random,
                    unsigned char byte) {
  WritableFilePtr f;
  Status s = WritableFile::Open(name, true, &f);
  if (!s.ok()) {
    LOG_ERROR << "failed to create file: " << name;
    exit(-1);
  }

  const size_t kBlockSize = 1024;
  unsigned char buf[kBlockSize];
  if (random) {
    Random rand;
    for (size_t i = 0; i < kBlockSize; ++i) {
      buf[i] = static_cast<unsigned char>(rand.Next() % 256);
    }
  } else {
    for (size_t i = 0; i < kBlockSize; ++i) {
      buf[i] = byte;
    }
  }

  size_t blocks = size / kBlockSize;
  size_t remain = size % kBlockSize;

  for (size_t i = 0; i < blocks; ++i)
    f->Append(Slice(reinterpret_cast<const char*>(buf), kBlockSize));
  if (remain > 0) f->Append(Slice(reinterpret_cast<const char*>(buf), remain));
  f->Sync();
}

bool CheckSameFile(const std::string& f1, const std::string& f2) {
  std::string h1 = Digestor::MD5File(f1);
  std::string h2 = Digestor::MD5File(f2);

  return h1 == h2;
}
}
